#include "TG_DATA_DEF.h"
#include "QQRealStreamItem.h"


UINT32 g_nTryTimes = 5;

struct tagPFrameHead
{
	UINT8 cSize;
	UINT8 cData[23];
};
static tagPFrameHead g_xPFrameHead[17] = 
{
	{13, {0x00,0x00,0x00,0x01,0x21,0x9a,0x04,0x0b,0x03,0x1c,0x00,0xc6,0x30}},
	{15, {0x00,0x00,0x00,0x01,0x21,0x9a,0x08,0x12,0xb4,0xa4,0x06,0xb8,0x01,0x8c,0x60} },
	{13, {0x00,0x00,0x00,0x01,0x21,0x9a,0x0c,0x1a,0xc0,0xb7,0x00,0x31,0x8c} },
	{17, {0x00,0x00,0x00,0x01,0x21,0x9a,0x10,0x22,0x4c,0x89,0x69,0x10,0x16,0xe0,0x06,0x31,0x80} },
	{13, {0x00,0x00,0x00,0x01,0x21,0x9a,0x14,0x2a,0x50,0x25,0xc0,0x0c,0x63} },
	{16, {0x00,0x00,0x00,0x01,0x21,0x9a,0x18,0x32,0x6d,0x2d,0x7e,0x40,0x43,0x80,0x18,0xc6} },
	{13, {0x00,0x00,0x00,0x01,0x21,0x9a,0x1c,0x3a,0x70,0x25,0xc0,0x0c,0x63} },
	{19, {0x00,0x00,0x00,0x01,0x21,0x9a,0x20,0x42,0x23,0x10,0x8d,0xff,0xa3,0x10,0x14,0xe0,0x06,0x31,0x80} },
	{14, {0x00,0x00,0x00,0x01,0x21,0x9a,0x24,0x4a,0x24,0x09,0x70,0x03,0x18,0xc0} },
	{18, {0x00,0x00,0x00,0x01,0x21,0x9a,0x28,0x52,0x2b,0x4b,0x5f,0xff,0x90,0x12,0xe0,0x06,0x31,0x80} },
	{14, {0x00,0x00,0x00,0x01,0x21,0x9a,0x2c,0x5a,0x2c,0x09,0x70,0x03,0x18,0xc0} },
	{19, {0x00,0x00,0x00,0x01,0x21,0x9a,0x30,0x62,0x33,0x22,0x5a,0x52,0x7f,0xfe,0x40,0x5b,0x80,0x18,0xc6} },
	{14, {0x00,0x00,0x00,0x01,0x21,0x9a,0x34,0x6a,0x34,0x09,0x70,0x03,0x18,0xc0} },
	{19, {0x00,0x00,0x00,0x01,0x21,0x9a,0x38,0x72,0x3b,0x4b,0x5f,0xff,0xff,0x90,0x12,0xe0,0x06,0x31,0x80} },
	{14, {0x00,0x00,0x00,0x01,0x21,0x9a,0x3c,0x7a,0x3c,0x09,0x70,0x03,0x18,0xc0} },
	{22, {0x00,0x00,0x00,0x01,0x21,0x9a,0x40,0x82,0x10,0xc2,0x08,0x77,0xff,0xff,0xfe,0x87,0x10,0x14,0xe0,0x06,0x31,0x80} },
	{14, {0x00,0x00,0x00,0x01,0x21,0x9a,0x44,0x8a,0x10,0x02,0x5c,0x00,0xc6,0x30} }
};

CRealStreamItem::CRealStreamItem(void)
{
	m_bNetServerSDK = false ;

	m_funCallBack = NULL;
	m_nContext    = 0;
	m_pContext    = NULL;

	m_hSocket        = NULL;	
}

CRealStreamItem::~CRealStreamItem(void)
{
	UnInitialize();
}

void CRealStreamItem::UnInitialize()
{
	DDThread::m_bThreadRun = false;
	DDThread::DDThdUnInit();

	m_bWaitForKeyFrame = TRUE;

	m_funCallBack = NULL;
	m_nContext    = 0;
	m_pContext    = NULL;

	m_nTimeOut         = 5;

	m_bWaitForKeyFrame = TRUE;

	m_nFirstDispTimeStamp = 0;
	m_nFirstDispSysTime   = 0;


	m_nNetBWState = Net_BW_State_1;

	m_nLastPacketFrameID = 0;


	m_nRecvFrameCount  = 0;
	m_nRecvPacketCount = 0;

	m_nLastFrameNum       = 0;
	m_nLastFrameTimeStamp = 0;

	m_bWaitFirstFrame    = TRUE;
	m_nFirstFrmTimeStamp = 0;
	memset(m_nNewestFrmHeadList,0,sizeof(m_nNewestFrmHeadList));
	m_nFirstFrmSysTime   = 0; 
	memset(m_nNewestFrmSysTimeStampList,0,sizeof(m_nNewestFrmSysTimeStampList));
}

int CRealStreamItem::Initialize(TG_REALSTREAM_INFO *pRealStreamInfo)
{
	UnInitialize();

	m_nLinkProtocol = pRealStreamInfo->xConnectInfo.nLinkProtocol;
	m_xConnectInfo  = pRealStreamInfo->xConnectInfo;
	m_nTimeOut      = pRealStreamInfo->xConnectInfo.nTimeOut;

	InitFrameList();

	return TG_ERR_SUCCESS;
}

int CRealStreamItem::StartRealStream(SOCKET hSocket,TG_REALSTREAM_INFO *pRealStreamInfo)
{
	m_bNetServerSDK = true ;

	Initialize(pRealStreamInfo);

	m_hSocket	  = hSocket ;

	m_nContext    = pRealStreamInfo->nContext;
	m_pContext    = pRealStreamInfo->pContext;
	m_funCallBack = pRealStreamInfo->funCallBack;

	m_pBeginFrame = &( m_xFrameList[0] );
	m_pBeginFrame->Reset();
	m_pEndFrame   = &( m_xFrameList[MAX_FRAME_COUNT-1] );

	if( !DDThread::DDThdInit() )
	{
		return TG_ERR_FAILURE;
	}
	return TG_ERR_SUCCESS;
}

int CRealStreamItem::vStartRealStream(TG_REALSTREAM_INFO *pRealStreamInfo)
{
	m_nContext    = pRealStreamInfo->nContext;
	m_pContext    = pRealStreamInfo->pContext;
	m_funCallBack = pRealStreamInfo->funCallBack;

	m_pBeginFrame = &( m_xFrameList[0] );
	m_pBeginFrame->Reset();
	m_pEndFrame   = &( m_xFrameList[MAX_FRAME_COUNT-1] );

	if( !DDThread::DDThdInit() )
	{
		return TG_ERR_FAILURE;
	}
	return TG_ERR_SUCCESS;
}

int CRealStreamItem::vStopRealStream()
{
	UnInitialize();

	return TG_ERR_SUCCESS;
}

int CRealStreamItem::ChangeLinkType(UINT16 nLinkType)
{
	

	return TG_ERR_SUCCESS;
}


#define DKQ_TIMEOUT_SLICE   10
#define DKQ_TIMEOUT_SLICE_2 6

int CRealStreamItem::DDThdDispatch()
{
	int nErrCode = -1;

	m_nFirstDispTimeStamp = 0;
	m_nFirstDispSysTime   = 0;


	DWORD dwLastTime = 0;
	DWORD dwCulTime  = 0;

	
	m_bWaitFirstFrame  = TRUE;
	m_bWaitForKeyFrame = TRUE;

	m_nNetBetterTimes  = 0;

	m_nRecvPacketCount = 0;
	m_nRecvFrameCount  = 0;

	UINT32 nTimeOut      = 0;
	UINT32 nTimeOutSlice = DKQ_TIMEOUT_SLICE;
 
	try
	{
		// Block until the socket is readable (with a 5-second timeout):
		fd_set rd_set,close_set;
		const unsigned numFds = m_hSocket+1;
		struct timeval timeout;
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;

		while( DDThread::m_bThreadRun )
		{
			FD_ZERO(&rd_set);
			FD_ZERO(&close_set);
			FD_SET((unsigned)m_hSocket, &rd_set);
			FD_SET((unsigned)m_hSocket, &close_set);

			timeout.tv_sec = 5;
			timeout.tv_usec = 0;

			int nResult = select(numFds, &rd_set, NULL, &close_set, &timeout);

			if( nResult > 0 )
			{
				if( DDThread::m_bThreadRun )
				{
					if( FD_ISSET(m_hSocket, &close_set) )
					{
						break;
					}
					if( FD_ISSET(m_hSocket, &rd_set) )
					{
						nErrCode = vTranslateRecv();
						///*
						if( TG_ERR_SUCCESS != nErrCode )
						{
							break ;
						}
						//*/
					}
				}
			}
		}
	}
	catch (...)
	{
	}

	if( DDThread::m_bThreadRun && NULL != m_funCallBack )
	{
		DDThread::m_bThreadRun = false;
		m_funCallBack(NULL,0,m_nContext,m_pContext);
	}

	return TG_ERR_SUCCESS;
}


int CRealStreamItem::RecvFrameHeadBuffer(SINT32 nNetBWState,UINT8 *pBuffer)
{
	TG_FRAME_HEAD *pFrameHead = (TG_FRAME_HEAD *)pBuffer;


	return 0;
}


int CRealStreamItem::vNetDisconnect()
{
	if( DDThread::m_bThreadRun && NULL != m_funCallBack )
	{
		DDThread::m_bThreadRun = false;
		m_funCallBack(NULL,0,m_nContext,m_pContext);
	}
	return TG_ERR_SUCCESS;
}




BOOL CRealStreamItem::InitFrameList()
{
	m_xFrameList.reserve(MAX_FRAME_COUNT);
	m_xFrameList.resize(MAX_FRAME_COUNT);

	m_xDataBlock.Allocate(MAX_CACHE_SIZE);
	for(int i=0;i<MAX_FRAME_COUNT-1;i++)
	{
		m_xFrameList[i].pNext = &m_xFrameList[i+1];
	}
	m_xFrameList[MAX_FRAME_COUNT-1].pNext = &m_xFrameList[0];

	m_pBeginFrame    = NULL;
	m_pEndFrame      = NULL;

	m_bWaitForKeyFrame = TRUE;

	return TRUE;
}

VOID CRealStreamItem::UnInitFrameList()
{

}


inline int CRealStreamItem::MoveBeginToNext()
{
	if( m_xDataBlock.nOffset1 == m_pBeginFrame->nOffset )
	{
		m_xDataBlock.nOffset1 = m_pBeginFrame->nOffset + m_pBeginFrame->nFrameSize;
		if( m_xDataBlock.nOffset1 == m_xDataBlock.nOffset2 )
		{
			m_xDataBlock.nOffset1 = 0;
			m_xDataBlock.nOffset2 = 0;
		}
		else
		{
			if( m_xDataBlock.nOffset1 > m_xDataBlock.nOffset2 &&
				0 == m_pBeginFrame->pNext->nOffset )
			{
				m_xDataBlock.nOffset1 = 0;
			}
		}
	}
	else //�˴���Ҫ����UDP�������µ�
	{

	}

	m_pBeginFrame->Reset();
	m_pBeginFrame = m_pBeginFrame->pNext;

	return 0;
}

int CRealStreamItem::CallBackFrame(UINT16 nFrameType,UINT8 *pFrame,UINT32 nFrameSize)
{
	m_nRecvFrameCount++;

	TG_FRAME_HEAD *pFrameHead = (TG_FRAME_HEAD *)pFrame;

	switch( nFrameType )
	{
	case TG_FRAME_TYPE_V_I:
		{
			//add
			m_nLastFrameNum       = 0;
			m_nLastFrameTimeStamp = pFrameHead->nTimeStamp;

			m_bWaitForKeyFrame = FALSE;
			m_funCallBack(pFrame,nFrameSize,m_nContext,m_pContext);
		}
		break;
	case TG_FRAME_TYPE_V_P:
	case TG_FRAME_TYPE_V_B:
		{
			if( !m_bWaitForKeyFrame )
			{
				UINT16 nFrameNum  = (UINT16)pFrameHead->nFrameNum;
				UINT32 nTimeStamp = (UINT32)pFrameHead->nTimeStamp;

				m_nLastFrameNum       = (UINT16)pFrameHead->nFrameNum;
				m_nLastFrameTimeStamp = (UINT32)pFrameHead->nTimeStamp;

				m_funCallBack(pFrame,nFrameSize,m_nContext,m_pContext);
			}
		}
		break;
	default:
		{
			m_funCallBack(pFrame,nFrameSize,m_nContext,m_pContext);
		}
		break;
	}
	return 0;
}
